/*
框架的入口容器文件 container.go
负责管理所有组件的生命周期
*/
package container

import (
	"gameServer/log"
	"os"        // 与操作系统交互的功能 （如创建通道、获取信号）
	"os/signal" // 提供信号处理功能（如监听系统中断信号）
	"syscall"   //定义系统调用常量（如中断信号SIGINT）
)

/* //* 框架容器实现，负责管理所有组件的生命周期，提供组件注册、初始化、启动和停止功能，支持优雅关闭 */

// Component 组件入口
type Component interface {
	// init 初始化组件
	Init() error
	// start 启动组件
	Start() error
	// stop 停止组件
	Stop() error
}

// Container 容器
type Container struct {
	components []Component
}

// 创建一个新容器
func NewContainer() *Container {
	return &Container{}
}

// Add 添加组件
func (c *Container) Add(component Component) {
	// 添加函数，目标组件添加进去
	c.components = append(c.components, component)
}

// Server 启动容器
func (c *Container) Server() {
	// 遍历组件，调用初始化函数
	for _, component := range c.components {
		if err := component.Init(); err != nil {
			log.Fatalf("component %T init failed: %v", component, err)
		}
	}
	// 启动所有组件
	for _, component := range c.components {
		if err := component.Start(); err != nil {
			log.Fatalf("component %T start failed: %v", component, err)
		}
	}

	// 等待组件终止信号
	// 通过信号捕捉实现优雅退出
	sigChan := make(chan os.Signal, 1)                      // 创建一个os.Signal的通道，缓冲区大小1
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // 这里的是两个终止信号，ctrl + c 或 kill 命令，通过Notify函数，进行监听两个信号
	// 这里通过函数Notify，一旦接收到信号就会放到管道中，然后管道才能弹出，否则会阻塞到这里
	// 通道接收操作，会阻塞当前 goroutine，直到sigChan中有信号到来（即收到中断信号）
	<-sigChan
	// sigChan<-

	// 停止所有组件
	for i := len(c.components) - 1; i >= 0; i-- {
		if err := c.components[i].Stop(); err != nil {
			log.Fatalf("component %T stop failed: %v", c.components[i], err)
		}
	}
}
